package common;

import com.alibaba.fastjson.JSON;
import common.configuration.AsyncFlowGetConfiguration;
import common.mongodb.MongoHelper;
import models.*;
import org.bson.Document;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 节点流程图
 */
public class AsyncFlowNodeGoJs {
    /**
     * 根据对应ID获取节点执行流程
     *
     * @param id MongoDB  ID
     * @return 节点集合和节点关系集合
     */
    public static GoJsEntity getGojsEntity(String id) {
        GoJsEntity goJsEntity = new GoJsEntity();
        AsyncFlowGetConfiguration configInfo = new AsyncFlowGetConfiguration();
        MongoHelper<AsyncFlowLogEntity> mongoHelper;
        mongoHelper = new MongoHelper<>(configInfo.getMongoDBConfigStr(), configInfo.getMongoDBName(), configInfo.getMongoDBTableName());
        Document asyncFlowLogDocument = mongoHelper.findById(id);
        AsyncFlowLogEntity appInfo = JSON.parseObject(asyncFlowLogDocument.toJson(), AsyncFlowLogEntity.class);
        addDefultNode(appInfo.getAsyncFlowNodeLogEntityList());
        goJsEntity.setGoJsNodeEntityList(getAllNodes(appInfo.getAsyncFlowNodeLogEntityList()));
        goJsEntity.setGoJsLinkDataEntityList(getLinkDataArray(appInfo.getAsyncFlowNodeLogEntityList()));
        goJsEntity.setAsyncFlowTitle(appInfo.getAsyncFlowModule());
        return goJsEntity;
    }

    public static AsyncFlowLogEntity getAsyncFlowLosList(String id) {
        AsyncFlowGetConfiguration configInfo = new AsyncFlowGetConfiguration();
        MongoHelper<AsyncFlowLogEntity> mongoHelper;
        mongoHelper = new MongoHelper<>(configInfo.getMongoDBConfigStr(), configInfo.getMongoDBName(), configInfo.getMongoDBTableName());
        Document asyncFlowLogDocument = mongoHelper.findById(id);
        AsyncFlowLogEntity appInfo = JSON.parseObject(asyncFlowLogDocument.toJson(), AsyncFlowLogEntity.class);
        return appInfo;
    }

    public static List<GoJsLinkDataEntity> getLinkDataArray(List<AsyncFlowNodeLogEntity> asyncFlowNodeLogEntityList) {
        LinkedList<GoJsLinkDataEntity> linkDataArray = new LinkedList<>();
        for (AsyncFlowNodeLogEntity asyncFlowNodeLogEntity : asyncFlowNodeLogEntityList) {
            getToLinkDataArray(asyncFlowNodeLogEntity, asyncFlowNodeLogEntityList, linkDataArray);
        }
        return linkDataArray;
    }


    private static void getToLinkDataArray(AsyncFlowNodeLogEntity thisAsyncFlowNodeLogEntity, List<AsyncFlowNodeLogEntity> asyncFlowNodeLogEntityList, List<GoJsLinkDataEntity> allLinkDataArray) {

        if (thisAsyncFlowNodeLogEntity == null) {
            return;
        }
        int allCount = asyncFlowNodeLogEntityList.size();
        int thisIndex = asyncFlowNodeLogEntityList.indexOf(thisAsyncFlowNodeLogEntity);
        boolean nextHasAsync = false;
        boolean hasValidator = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 1);
        boolean hasGetData = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7);
        boolean hasOperator = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 3);
        boolean hasBaseSave = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 4);
        boolean hasSync = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 5);
        boolean hasASync = asyncFlowNodeLogEntityList.stream().anyMatch(c -> c.getExecuteEnumCode() == 6);
        for (int i = thisIndex + 1; i < allCount; i++) {
            GoJsLinkDataEntity linkData = new GoJsLinkDataEntity();
            AsyncFlowNodeLogEntity asyncFlowNodeLogEntity = asyncFlowNodeLogEntityList.get(i);
            linkData.setFrom(thisAsyncFlowNodeLogEntity.getLogFileName());
            if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 1) {
                if (asyncFlowNodeLogEntity.getExecuteEnumCode() != 1 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 2 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 7 && hasGetData) {
                    break;
                }
            } else if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 2 || thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 7) {
                if (asyncFlowNodeLogEntity.getExecuteEnumCode() != 2 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 7 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 3 && hasOperator) {
                    break;
                }
            } else if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 3) {
                if (asyncFlowNodeLogEntity.getExecuteEnumCode() != 4 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 3 && hasBaseSave) {
                    break;
                }
            } else if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 4) {
                if (asyncFlowNodeLogEntity.getExecuteEnumCode() != 5 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 4 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 6) {
                    break;
                }
            } else if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() == 5) {
                if (asyncFlowNodeLogEntity.getExecuteEnumCode() != 6 && asyncFlowNodeLogEntity.getExecuteEnumCode() != 5) {
                    break;
                }
            }

            if (thisAsyncFlowNodeLogEntity.isAsync()) {
                if (!asyncFlowNodeLogEntity.isAsync()) {
                    linkData.setTo(asyncFlowNodeLogEntity.getLogFileName());
                    allLinkDataArray.add(linkData);
                    break;
                } else {
                    if (thisAsyncFlowNodeLogEntity.getExecuteEnumCode() != asyncFlowNodeLogEntity.getExecuteEnumCode()) {
                        linkData.setTo(asyncFlowNodeLogEntity.getLogFileName());
                        allLinkDataArray.add(linkData);
                    }
                }
            } else {
                if (!asyncFlowNodeLogEntity.isAsync()) {
                    if (nextHasAsync) {
                        break;
                    }
                    linkData.setTo(asyncFlowNodeLogEntity.getLogFileName());
                    allLinkDataArray.add(linkData);
                    break;
                } else {
                    nextHasAsync = true;
                    linkData.setTo(asyncFlowNodeLogEntity.getLogFileName());
                    allLinkDataArray.add(linkData);
                }
            }
        }
    }

    public static List<GoJsNodeEntity> getAllNodes(List<AsyncFlowNodeLogEntity> appInfo) {
        List<GoJsNodeEntity> asyncFlowNodeDataArrays = new ArrayList<>();
        for (AsyncFlowNodeLogEntity asyncFlowNodeLogEntity : appInfo) {
            GoJsNodeEntity asyncFlowNodeDataArray = new GoJsNodeEntity();

            asyncFlowNodeDataArray.setKey(asyncFlowNodeLogEntity.getLogFileName());
            asyncFlowNodeDataArray.setParent("");
            asyncFlowNodeDataArray.setName(asyncFlowNodeLogEntity.getLogMethodName());
            asyncFlowNodeDataArray.setSource("");
            asyncFlowNodeDataArrays.add(asyncFlowNodeDataArray);

        }
        return asyncFlowNodeDataArrays;
    }

    private static void addDefultNode(List<AsyncFlowNodeLogEntity> appInfo) {
        boolean hasValidator = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 1);
        boolean hasGetData = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7);
        boolean hasOperator = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 3);
        boolean hasBaseSave = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 4);
        boolean hasSync = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 5);
        boolean hasASync = appInfo.stream().anyMatch(c -> c.getExecuteEnumCode() == 6);

        if (!hasValidator) {
            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
            addAsyncFlowNodeLogEntity.setLogMethodName("验证");
            addAsyncFlowNodeLogEntity.setLogFileName("defaultValidator");
            addAsyncFlowNodeLogEntity.setExecuteEnumCode(1);
            appInfo.add(0, addAsyncFlowNodeLogEntity);
        }
        if (hasGetData) {
            long indexstart = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1).count();
            if (appInfo.get((int) (indexstart - 1)).isAsync()) {
                AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
                addAsyncFlowNodeLogEntity.setLogMethodName("验证结束开始查询");
                addAsyncFlowNodeLogEntity.setLogFileName("addValidatorGetData");
                addAsyncFlowNodeLogEntity.setExecuteEnumCode(2);
                appInfo.add((int) indexstart, addAsyncFlowNodeLogEntity);

            }

            long indexend = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7).count();
            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
            addAsyncFlowNodeLogEntity.setLogMethodName("查询结束开始操作");
            addAsyncFlowNodeLogEntity.setLogFileName("addGetDataOperator");
            addAsyncFlowNodeLogEntity.setExecuteEnumCode(3);
            appInfo.add((int) indexend, addAsyncFlowNodeLogEntity);

        }
        if (!hasGetData && (hasOperator || hasBaseSave || hasSync || hasASync)) {
            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
            long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1).count();
            addAsyncFlowNodeLogEntity.setLogMethodName("验证结束");
            addAsyncFlowNodeLogEntity.setLogFileName("ValidatorEND");
            addAsyncFlowNodeLogEntity.setExecuteEnumCode(1);
            appInfo.add((int) index, addAsyncFlowNodeLogEntity);
        }
        if (hasOperator) {
            if (!hasBaseSave && (hasSync || hasASync)) {

                long indexend = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7 || c.getExecuteEnumCode() == 3).count();
                AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
                String type = "";
                if (hasSync && hasASync) {
                    type = "开始执行同步异步";
                } else if (hasSync) {
                    type = "开始执行同步";
                } else {
                    type = "开始执行异步";
                }
                addAsyncFlowNodeLogEntity.setLogMethodName("操作结束" + type);
                addAsyncFlowNodeLogEntity.setLogFileName("OperatorEND");
                addAsyncFlowNodeLogEntity.setExecuteEnumCode(3);
                appInfo.add((int) indexend, addAsyncFlowNodeLogEntity);

            }
//            if (!hasBaseSave && hasSync && hasASync) {
//                AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
//                long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7 || c.getExecuteEnumCode() == 3).count();
//                addAsyncFlowNodeLogEntity.setLogMethodName("操作结束开始执行同步");
//                addAsyncFlowNodeLogEntity.setLogFileName("addOperatorSync");
//                addAsyncFlowNodeLogEntity.setExecuteEnumCode(3);
//                appInfo.add((int) index, addAsyncFlowNodeLogEntity);
//            }
//            if (!hasBaseSave && hasASync) {
//                AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
//                long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 3 || c.getExecuteEnumCode() == 7).count();
//                addAsyncFlowNodeLogEntity.setLogMethodName("操作结束开始执行异步");
//                addAsyncFlowNodeLogEntity.setLogFileName("addOperatorAsync");
//                addAsyncFlowNodeLogEntity.setExecuteEnumCode(4);
//                hasBaseSave = true;
//                appInfo.add((int) index, addAsyncFlowNodeLogEntity);
//            }

        }
//        if (!hasOperator && hasGetData && (hasBaseSave || hasSync || hasASync)) {
//            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
//            long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 7).count();
//            addAsyncFlowNodeLogEntity.setLogMethodName("操作");
//
//            addAsyncFlowNodeLogEntity.setLogFileName("defaultOperator");
//            addAsyncFlowNodeLogEntity.setExecuteEnumCode(3);
//            hasOperator = true;
//            appInfo.add((int) index, addAsyncFlowNodeLogEntity);
//        }

//        if (!hasSync & hasBaseSave && hasASync) {
//            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
//            long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 3 || c.getExecuteEnumCode() == 4 || c.getExecuteEnumCode() == 7).count();
//            addAsyncFlowNodeLogEntity.setLogMethodName("同步");
//            addAsyncFlowNodeLogEntity.setLogFileName("defaultSync");
//            addAsyncFlowNodeLogEntity.setExecuteEnumCode(5);
//            appInfo.add((int) index, addAsyncFlowNodeLogEntity);
//        }
//        if (!hasASync & hasSync) {
//            AsyncFlowNodeLogEntity addAsyncFlowNodeLogEntity = new AsyncFlowNodeLogEntity();
//            long index = appInfo.stream().filter(c -> c.getExecuteEnumCode() == 1 || c.getExecuteEnumCode() == 2 || c.getExecuteEnumCode() == 3 || c.getExecuteEnumCode() == 4 || c.getExecuteEnumCode() == 5 || c.getExecuteEnumCode() == 7).count();
//            addAsyncFlowNodeLogEntity.setLogMethodName("异步");
//            addAsyncFlowNodeLogEntity.setLogFileName("defaultASync");
//            addAsyncFlowNodeLogEntity.setExecuteEnumCode(6);
//            appInfo.add((int) index, addAsyncFlowNodeLogEntity);
//        }
    }
}
